package cn.jcby.app.filter;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.google.gson.Gson;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;

/**
 * SpringBoot AOP打印请求参数与响应参数
 */

@Aspect
@Order(5)
@Component

public class ControllerLogAspect {

    private static final Logger log = LoggerFactory.getLogger(ControllerLogAspect.class);

    @Pointcut("execution(* cn.jcby.app..*.*(..))")
    public void controllerLog() {
    }

    @Before("controllerLog()")
    public void doBefore(JoinPoint joinPoint) throws Throwable {

        // 接收到请求，记录请求内容
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (attributes!=null) {
            HttpServletRequest request = attributes.getRequest();

            if ("POST".equals(request.getMethod().toUpperCase()) || "PUT".equals(request.getMethod().toUpperCase())) {
                // 记录下请求内容
                log.debug("********************************************");
                log.debug("请求URL : " + request.getRequestURL());
                log.debug("客户端ip [" + request.getRemoteAddr() + "]");
                log.debug("请求映射 : 【" + joinPoint.getSignature().getDeclaringTypeName() + "】类的【" + joinPoint.getSignature().getName() + "】方法");

                // 获取参数, 只取自定义的参数, 自带的HttpServletRequest, HttpServletResponse不管
                if (joinPoint.getArgs().length > 0) {
                    for (Object o : joinPoint.getArgs()) {
                        if (o instanceof HttpServletRequest
                                || o instanceof HttpServletResponse
                    ||o instanceof MultipartFile
                        ||o instanceof LambdaQueryWrapper
                        || o instanceof List
                        || o instanceof String) {
                            continue;
                        }
                        try {
                            log.info("参数 : " + new Gson().toJson(o));
                        } catch (Exception ex) {
                            log.info(request.getRequestURI()+",参数Json转换异常");
                        }

                    }
                }
            }

            if ("GET".equals(request.getMethod())) {

                log.debug("请求URL : " + request.getRequestURL());
                log.debug("请求IP : " + request.getRemoteAddr());
                log.debug("请求映射 : 【" + joinPoint.getSignature().getDeclaringTypeName() + "】类的【" + joinPoint.getSignature().getName() + "】方法");

                // 获取参数, 只取自定义的参数, 自带的HttpServletRequest, HttpServletResponse不管
                if (joinPoint.getArgs().length > 0) {
                    for (Object o : joinPoint.getArgs()) {
                        if (o instanceof HttpServletRequest || o instanceof HttpServletResponse) {
                            continue;
                        }
                        log.debug("请求参数 : " + JSONObject.toJSONString(o));
                    }
                }
            }
        }
    }


    @AfterReturning(returning = "ret", pointcut = "controllerLog()")
    public void doAfterReturning(Object ret) throws Throwable {
        // 处理完请求，返回内容
        /*try {
            log.debug("返回 : " + JSONObject.toJSONString(ret));
        }catch (Exception ex){
            ex.printStackTrace();
        }*/

        log.debug("请求结束 : " + "********************************************");
    }

}
